package onion.mqtt.server.manager;

import onion.mqtt.server.store.MessageStore;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * @author Mr, Lu
 * @developmentTeam 浙江允泽信息科技有限公司
 * @createTime 2023/12/12
 */
public class MessageManager {
    static final Logger log = LoggerFactory.getLogger(MessageManager.class);
    private volatile static MessageManager INSTANCE;

    /**
     * 遗嘱消息
     */
    private final Map<String, List<MessageStore>> willMessageMap = new ConcurrentHashMap<>();

    /**
     * 保留消息
     */
    private final Map<String, List<MessageStore>> retainMessageMap = new ConcurrentHashMap<>();

    private MessageManager() {}

    /**
     * 单例模式，获取对象
     * @return
     */
    public static MessageManager getInstance() {
        if (INSTANCE == null) {
            synchronized (MessageManager.class) {
                if (INSTANCE == null) {
                    INSTANCE = new MessageManager();
                }
            }
        }
        return INSTANCE;
    }

    /**
     * 添加遗嘱消息
     *
     * @param messageStore
     */
    public synchronized void addWillMessage(MessageStore messageStore) {
        String topic = messageStore.getTopic();
        if (willMessageMap.containsKey(topic)) {
            willMessageMap.get(topic).add(messageStore);
        } else {
            ArrayList<MessageStore> messageStores = new ArrayList<>();
            messageStores.add(messageStore);
            willMessageMap.put(topic, messageStores);
        }
        log.debug("client addWillMessage, clientId: {}, topic: {}, total: {}", topic, messageStore.getClientId(), willMessageMap.size());
    }

    /**
     * 移除遗嘱消息
     *
     * @param topic
     */
    public synchronized void removeWillMessage(String topic) {
        if (!willMessageMap.containsKey(topic)) {
            return;
        }
        willMessageMap.remove(topic);
    }

    /**
     * 移除遗嘱消息，根据客户端id移除
     *
     * @param clientId
     */
    public synchronized void removeWillMessageByClient(String clientId) {
        willMessageMap.values().forEach(s -> s.removeIf(sb -> clientId.equals(sb.getClientId())));
    }

    /**
     * 获取遗嘱消息
     * @param topic
     * @return
     */
    public List<MessageStore> getWillMessage(String topic) {
        return willMessageMap.get(topic) == null ? new ArrayList<>() : willMessageMap.get(topic);
    }

    /**
     * 获取遗嘱消息，根据客户端id
     * @param clientId
     * @return
     */
    public List<MessageStore> getWillMessageByClient(String clientId) {
        List<MessageStore> list = new ArrayList<>();
        willMessageMap.values().forEach(s -> {
            List<MessageStore> collect = s.stream().filter(sb -> clientId.equals(sb.getClientId())).collect(Collectors.toList());
            list.addAll(collect);
        });
        return list;
    }

    /**
     * 添加保留消息
     * @param messageStore
     */
    public synchronized void addRetainMessage(MessageStore messageStore) {
        String topic = messageStore.getTopic();
        if (retainMessageMap.containsKey(topic)) {
            retainMessageMap.get(topic).add(messageStore);
        } else {
            ArrayList<MessageStore> messageStores = new ArrayList<>();
            messageStores.add(messageStore);
            retainMessageMap.put(topic, messageStores);
        }
        log.debug("client addRetainMessage, clientId: {}, topic: {}, total: {}", topic, messageStore.getClientId(), retainMessageMap.size());
    }

    /**
     * 移除保留消息
     * @param topic
     */
    public synchronized void removeRetainMessage(String topic) {
        if (!retainMessageMap.containsKey(topic)) {
            return;
        }
        retainMessageMap.remove(topic);
    }

    /**
     * 获取保留消息
     * @param topic
     * @return
     */
    public List<MessageStore> getRetainMessage(String topic) {
        return retainMessageMap.get(topic) == null ? new ArrayList<>() : retainMessageMap.get(topic);
    }

    /**
     * 获取保留消息，根据客户端id
     * @param clientId
     * @return
     */
    public List<MessageStore> getRetainMessageByClient(String clientId) {
        List<MessageStore> list = new ArrayList<>();
        retainMessageMap.values().forEach(s -> {
            List<MessageStore> collect = s.stream().filter(sb -> clientId.equals(sb.getClientId())).collect(Collectors.toList());
            list.addAll(collect);
        });
        return list;
    }
}
